/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright 2010 huliqing, huliqing.cn@gmail.com
 *
 * This file is part of QFaces.
 * QFaces is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * QFaces is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with QFaces.  If not, see <http://www.gnu.org/licenses/>.
 *
 * 这个文件是QFaces的一部分。
 * 您可以单独使用或分发这个文件，但请不要移除这个头部声明信息.
 * QFaces是一个自由软件，您可以自由分发、修改其中的源代码或者重新发布它，
 * 新的任何修改后的重新发布版必须同样在遵守LGPL3或更后续的版本协议下发布.
 * 关于LGPL协议的细则请参考COPYING、COPYING.LESSER文件，
 * 您可以在QFaces的相关目录中获得LGPL协议的副本，
 * 如果没有找到，请连接到 http://www.gnu.org/licenses/ 查看并获取副本。
 *
 * - Author: Huliqing
 * - Contact: huliqing.cn@gmail.com
 * - License: GNU Lesser General Public License (LGPL)
 * - Blog and source code availability: http://www.huliqing.name/
 */

Q.F = {
    contextPath : null,	// Context path
    suffix : null,	// QFaces suffix mapping
    viewId : null,
    filterName : null,	// Filter name, defaul is "qfaces_filter"
    loadingSrc : null,	// “loading” Image src
    flag : null,        // "loading" image
    actionURI  : null,	// Action URI
    uis : new Array(),	// Include all UI
    put : function(clientId, UI) {
        this.uis[clientId] = UI;
        if (clientId.indexOf(":") != -1) {
            var shortId = clientId.substring(clientId.lastIndexOf(":") + 1);
            this.uis[shortId] = UI;
        }
    },
    find : function(clientId) {
        var ui = this.uis[clientId];
        if (ui == null)
            Q.debug("Component not found by id=" + clientId);
        return ui;
    },
    loading : function(p, obj) {
        if (!this.flag)
            this.getLoading();
        p = (false == p ? false : true);
        this.flag.style.position = "absolute";
        this.flag.style.zIndex = Q.U.zIndex++;
        this.flag.style.display = (p ? "" : "none");
        document.body.appendChild(this.flag);
        var point = (obj != null ? Q.U.getPosition(Q.get(obj)) : Q.U.getMousePosition());
        if (point != null)
            Q.U.setPosition(this.flag, point.x, point.y);
    },
    getLoading : function() {
        if (!this.flag) {
            this.flag = document.createElement("img");
            this.flag.src = this.loadingSrc;
            this.flag.style.position = "absolute";
            document.body.appendChild(this.flag);
        }
        this.flag.style.display = "";
        return this.flag;
    },
    getActionURI : function() {
        if (this.actionURI != null) return this.actionURI;
        this.actionURI = Q.F.contextPath + Q.F.viewId + "";
        if (this.actionURI.indexOf(".") != -1) {
            this.actionURI = this.actionURI.substring(0, this.actionURI.lastIndexOf(".")) + "." + Q.F.suffix;
        } else {
            this.actionURI = this.actionURI + "." + Q.F.suffix;
        }
        return this.actionURI;
    },
    getViewState : function() {
        var encodedState;
        var stateElements = window.document.getElementsByName("javax.faces.ViewState");
        var stateValue = null;
        if (null != stateElements && 0 < stateElements.length) {
            stateValue = stateElements[0].value;
            var uriEncodedState = encodeURI(stateValue);
            var rexp = new RegExp("\\+", "g");
            encodedState = uriEncodedState.replace(rexp, "\%2B");
        }
        return encodedState;
    }
}
QFaces.Faces = Q.F;
Q.F.Ajax = {
    ajax : new Array(),	// 存放并管理所有组件的ajax请求信息
    // 立即取消前一个Ajax处理，并重建一个(不要使用队列)
    build : function(clientId) {
        var processor = this.ajax[clientId];
        if (processor != null) {
            processor.stop();
        }
//        Q.debug("Rebuild ajax processor by clientId = " + clientId);
        this.ajax[clientId] = new Q.F.Ajax.Processor(clientId, Q.U.getXmlRequest());
        return this.ajax[clientId];
    },
    find : function(clientId) {
        return this.ajax[clientId];
    },
    onreadyStatechange : function(processor) {
        if (processor == null) {
            Q.debug("Ajax processor not found!");
            return;
        }
        if (processor.isStopped()) {
            Q.debug("Ajax processor has stopped! processor.request.readyState=" + processor.request.readyState);
            return;
        }
        // 这个方法里面如果出现readyState == 0,则可能是processor已经处于stopped状态
        if (processor.request.readyState == 0) {
//            Q.debug("Ajax,request, readyState=" + processor.request.readyState);
            return;
        } else if (processor.request.readyState == 1) {
//            Q.debug("Ajax,request, readyState=" + processor.request.readyState);
        } else if (processor.request.readyState == 2) {
//            Q.debug("Ajax,request, readyState=" + processor.request.readyState);
        } else if (processor.request.readyState == 3) {
//            Q.debug("Ajax,request, readyState=" + processor.request.readyState);
        } else if (processor.request.readyState == 4) {
//            Q.debug("Ajax,OK,readyState = " + processor.request.readyState);
            if (processor.request.status == 200) {
//                Q.debug("Ajax,request successfull,status" + processor.request.status);
//                Q.debug("Ajax,result = " + processor.request.responseText);
                processor.process.apply();
                Q.F.Ajax.ajax[processor.clientId] = null;
            } else if (processor.request.status == 401) {
                Q.debug("Ajax,Error:" + processor.request.status);
            } else if (processor.request.status == 403) {
                Q.debug("Ajax,Error:" + processor.request.status);
            } else if (processor.request.status == 404) {
                Q.debug("Ajax,Error:" + processor.request.status);
            } else if (processor.request.status == 500) {
                Q.debug("Ajax,Error:" + processor.request.status);
                Q.debug("Ajax,Error, Message=:" + processor.request.responseText);
            }
            return;
        } else {
            Q.debug("Ajax,Error,unknow state, readyState=" + processor.request.readyState);
        }
        Q.U.setTimeout(Q.F.Ajax.onreadyStatechange, 50, processor);
    }
}
Q.F.Ajax.Processor = function(clientId, requestAjax) {
    this.clientId = clientId;
    this.request = requestAjax;
    this.param = new Array();
    this.process = null;
    this.stopped = false;
    this.put = function(key, value) {
        var map = new Array(2);
        map[0] = key;
        map[1] = value;
        this.param.push(map);
        return this;
    }
    this.getValues = function() {
        return this.baseValue(this.param);
    }
    this.postValues = function() {
        return this.baseValue(this.param) + "javax.faces.ViewState=" + Q.F.getViewState();
    }
    this.baseValue = function(array) {
        var temp = "";
        for (var i = 0; i < array.length; i++) {
            var map = array[i];
            temp += map[0] + "=" + Q.U.encodeURI(map[1]) + "&";
        }
//        Q.debug("baseValue=" + temp);
        return temp;
    }
    this.setProcess = function(fun) {
        this.process = fun;
    }
    this.preSend = function() {
        this.request.open("POST", Q.F.getActionURI(), true);
        this.request.setRequestHeader("Content-Type","application/x-www-form-urlencoded;charset=utf-8");
        try {
            this.request.onreadyStatechange = Q.F.Ajax.onreadyStatechange(this);
        } catch (e) {
            Q.debug("Error=" + e);
        } // Catch exception when use ie6 (When using IE6, the error may occur)
    }
    this.get = function() {
        this.preSend();
        this.request.send(this.getValues());
    }
    this.post = function() {
        this.preSend();
        this.request.send(this.postValues());
    }
    this.stop = function() {
//        Q.debug("====Stop Request(clientId:\"" + this.clientId + "\")====");
        this.stopped = true;
        if (this.request != null) {
            this.request.abort();
        }
    }
    this.isStopped = function() {
        return this.stopped;
    }
}
Q.F.Filter = {
    build : function() {
        var p = new Q.F.Filter.Processor();
        return p;
    }
}
Q.F.Filter.Processor = function() {
    this.param = new Array();
    this.put = function(key, value) {
        var map = new Array(2);
        map[0] = key;
        map[1] = value;
        this.param.push(map);
        return this;
    }
    this.baseValue = function(array) {
        // filterName标识为Filter处理器
        var temp = Q.F.filterName + "=true&";
        for (var i = 0; i < array.length; i++) {
            var map = array[i];
            temp += map[0] + "=" + Q.U.encodeURI(map[1]) + "&";
        }
        return temp;
    }
    this.getResult = function() {
        var resultURI = Q.F.getActionURI() + "?" + this.baseValue(this.param);
        return resultURI;
    }
}